package edu.sjtu.grid.workflow.facts;

import java.io.File;
import java.net.URL;
import java.util.ArrayList;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import edu.sjtu.grid.workflow.Util;
import edu.sjtu.grid.workflow.group.GroupGraph;
import edu.sjtu.grid.workflow.iterator.UpwardRankIterator;
import edu.sjtu.grid.workflow.schedule.CheapestSchedule;
import edu.sjtu.grid.workflow.schedule.HEFTSchedule;
import edu.sjtu.grid.workflow.schedule.HeuristicSearchSchedule;
import edu.sjtu.grid.workflow.schedule.HeuristicSearchSchedule_AvgCost;
import edu.sjtu.grid.workflow.schedule.HeuristicSearchSchedule_AvgCost_Wait;
import edu.sjtu.grid.workflow.schedule.HeuristicSearchSchedule_InitialCost;
import edu.sjtu.grid.workflow.schedule.ScheduleBase;
import edu.sjtu.grid.workflow.schedule.MDPSearchSchedule;

public class Facts {

	private String fileName = null;
	private PCS pcs = null;
	private ADAG adag = null;
	private Runs runs = null;
	
	private GroupGraph groupGraph = null;
	
	public void saveRunsToXmlFile()
	{
		File f = new File(this.fileName);
		String dir = f.getParent();
		String file = dir + "/runs.xml";
		String text = this.runs.toXML("", "    ");
		Util.saveToNewFile(file, text);
	}
	
	public boolean loadXmlFile(String fileName)
	{
		this.fileName = fileName;
		Document document = null;
		try {
			document = new SAXReader().read((new URL("file:" + this.fileName)));
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		
		Element eFacts = document.getRootElement();
		Element ePCS = eFacts.element("pcs");
		Element eADAG = eFacts.element("adag");
		Element eRuns = eFacts.element("runs");
		
		this.pcs = new PCS(this, ePCS);
		this.adag = new ADAG(this, eADAG);
		this.runs = new Runs(this, eRuns);

		this.groupGraph = new GroupGraph(this);
		
        return true;
	}
	
	public String toString()
	{
		StringBuilder s = new StringBuilder();
		s.append("=============" + this.fileName + "=============\n\n");
		s.append(this.pcs.toString()+"\n");
		s.append(this.adag.toString()+"\n");
		s.append(this.runs.toString());
		return s.toString();
	}

	public String getFileName() {
		return fileName;
	}

	public PCS getPcs() {
		return pcs;
	}

	public ADAG getAdag() {
		return adag;
	}

	public Runs getRuns() {
		return runs;
	}
	
	public GroupGraph getGroupGraph()
	{
		return groupGraph;
	}
	
	public static void main(String[] args) {
		
		ArrayList<String> files = new ArrayList<String>();
		ArrayList<Double> units = new ArrayList<Double>();
		ArrayList<Double> deadlines = new ArrayList<Double>();
		
		//files.add("facts/leadmm1/facts.xml");units.add((double)0); deadlines.add((double)1.5);
		//files.add("facts/leadmm2/facts.xml");units.add((double)0); deadlines.add((double)150);
		//files.add("facts/leadmm3/facts.xml");units.add((double)0); deadlines.add((double)20);
		//files.add("facts/leadmm4/facts.xml");units.add((double)0.01); deadlines.add((double)10);
		
		/*------------------------choose Epigenomics------------------------*/
		files.add("facts/Epigenomics_24/facts.xml"); units.add((double)5); deadlines.add((double)1000);
		/*
		 * HEFT		797.6	124778
		 * HEU		876		105776
		 * HEU_Avg	884		106167
		 * HEU_Init	897		107190
		 * MDP		900		105456
		 */

		//files.add("facts/Epigenomics_46/facts.xml"); units.add((double)1); deadlines.add((double)4000);
		/*
		 * HEFT		1724	273301
		 * HEU		3951	217004
		 * HEU_Avg	3996	188841
		 * HEU_Init	3999	237945
		 * MDP		3944	199656
		 */
		
		//files.add("facts/Epigenomics_100/facts.xml"); units.add((double)20); deadlines.add((double)20000);//15349.52
		//files.add("facts/Epigenomics_997/facts.xml"); units.add((double)500); deadlines.add((double)500000);//138883.19

		
		
		/*------------------------choose Inspiral------------------------*/
		//files.add("facts/Inspiral_30/facts.xml");units.add((double)1); deadlines.add((double)600);
		/*
		 * HEFT		262.3	45334
		 * HEU		599		33302
		 * HEU_Avg	598		36990
		 * HEU_Init	599		33302
		 * MDP		596		32989
		 */

		//files.add("facts/Inspiral_50/facts.xml");units.add((double)1); deadlines.add((double)10000);

		
		/*------------------------choose Montage------------------------*/
		//files.add("facts/Montage_25/facts.xml");units.add((double)1); deadlines.add((double)4000);
		/*
		 * HEFT		1012.8	146585
		 * HEU		3992	91594
		 * HEU_Avg	3999	107303
		 * HEU_Init	3795	130991
		 * MDP		3997	91290
		 */
		//files.add("facts/Montage_50/facts.xml");units.add((double)100); deadlines.add((double)10000);
		//??files.add("facts/Montage_100/facts.xml");units.add((double)1); deadlines.add((double)42);
		//??files.add("facts/Montage_1000/facts.xml"); units.add((double)1); deadlines.add((double)1000);
		
		/*------------------------choose CyberShake------------------------*/
		//files.add("facts/CyberShake_30/facts.xml");units.add((double)1); deadlines.add((double)4000);
		/*
		 * HEFT		3458	518007
		 * HEU		3999	443770
		 * HEU_Avg	3999	451332
		 * HEU_Init	3977	454091
		 * MDP		3999	443770
		 */
		//files.add("facts/CyberShake_50/facts.xml");units.add((double)1); deadlines.add((double)10000);
		/*
		 * HEFT		5283		981433
		 * HEU		9999		787804
		 * HEU_Avg	9999		802512
		 * HEU_Init	9999		856587
		 * MDP		9999		787804
		 */
		
		Facts f = new Facts();
		ScheduleBase s = null;
		for(int k=0; k<files.size(); k++)
		{
			String file = files.get(k);
			Double deadline = deadlines.get(k);
			Double unit = units.get(k);
			
			if(f.loadXmlFile(file))
			{
				//facts string
				//System.out.println(f.toString());
				
				//upward rank
				/*UpwardRankIterator i = f.getAdag().getUpwardRankIterator();
				System.out.println("----------UpwardRank----------");
				int j = 0;
				System.out.println("rank\tindex\tid\t\tvalue");
				while(i.hasNext())
				{
					Job job = (Job)i.next();
					System.out.println(j++ + "\t" 
							+ job.getIndex() + "\t"
							+ Util.formatOutputString(job.getId(), 2)
							+ Util.formatOutputDouble(job.getUpwardRank())
							);
				}
				System.out.println();*/
				
				//cheapest
				//s = new CheapestSchedule(f);
				//s.schedule();
				//System.out.println(s.toString());
				
				//HEFT
				s = new HEFTSchedule(f);
				s.schedule();
				System.out.println(s.toString());
				
				//HeuristicSearch
				//s = new HeuristicSearchSchedule(f, deadline);
				//s.schedule();
				//System.out.println(s.toString());
				
				//HeuristicSearch_AvgCost
				s = new HeuristicSearchSchedule_AvgCost(f, deadline);
				s.schedule();
				System.out.println(s.toString());
				
				//HeuristicSearch_AvgCost_Wait
				s = new HeuristicSearchSchedule_AvgCost_Wait(f, deadline);
				s.schedule();
				System.out.println(s.toString());
				
				//HeuristicSearchSchedule_InitialCost
				//s = new HeuristicSearchSchedule_InitialCost(f, deadline);
				//s.schedule();
				//System.out.println(s.toString());
				
				
				//MDPSearch
				//s = new MDPSearchSchedule(f, deadline, unit);
				//s.schedule();
				//System.out.println(s.toString());
				
				//xml
				//System.out.println(f.getRuns().toXML("", "    "));
				//f.saveRunsToXmlFile();
			}
		}
	}
}
